#include <iostream>
#include <fstream>

using std::cout;
using std::endl;
using std::ofstream;


template <class T>
struct Default_Deleter
{
    void operator()(T * p) {
        delete p;
    } 
};


template <class T, class Deleter=Default_Deleter<T>>
class RAII
{
public:
    RAII(T * p)
    : _p(p), _deletor()
    {   cout << "RAII(T*)" << endl; }

    ~RAII()
    {
        cout << "~RAII()" << endl;
        if(_p) {
            //delete _p; //这里被写死了
            //调用一个函数来完成资源的回收
            _deletor(_p);//封装了变化
            _p = nullptr;
        }
    }

    T * operator->()
    {   return _p;  }

    T & operator*()
    {   return *_p;    }

    RAII(const RAII & ) = delete;
    RAII & operator=(const RAII &) = delete;

private:
    T * _p;//_p指向的是申请的资源
    Deleter _deletor;//函数对象
};

class Point
{
public:
    Point(int ix, int iy)
    : _ix(ix)
    , _iy(iy)
    {   cout << "Point(int,int)" << endl;   }

    ~Point()
    {   cout << "~Point()" << endl; }

    void print() const
    {   
        cout << "(" << _ix
             << "," << _iy
             << ")" << endl;
    }

private:
    int _ix;
    int _iy;
};

void test0()
{
    Point * pt = new Point(1, 2);
    pt->print();
    Default_Deleter<Point> pobj;
    pobj(pt);
}

struct OfstreamCloser
{
    void operator()(ofstream * pofs)
    {
        if(pofs) {
            pofs->close();
            cout << ">> ofstream.close()" << endl;
        }
    }
};

void test1()
{
    ofstream ofs("1.txt", std::ios::app);
    if(!ofs.good()) {
        cout << "ofstream open file error" << endl;
        return ;
    }
    //指定第二个模板参数为OfstreamCloser
    RAII<ofstream, OfstreamCloser> raii(&ofs);

    ofs << "this is a deletor test\n";


    //希望以下语句能自动执行，防止忘了调用文件输出流的close函数
    //ofs. close();//关闭文件输出流流
}


int main()
{
    test1();

#if 0
    RAII<Point> raii(new Point(1, 2));
    raii->print();
    (raii.operator->())->print();
#endif
    
    /* test0(); */

    return 0;
}

